﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Web;

namespace OldStyleDiagnosticsSampleApp
{

    public class TraceIt
    {
        public static TraceSource App = new TraceSource("app");
        static TraceIt()
        {
            App.Listeners.Clear();
        }

        public static void EnableTrace()
        {
            TraceListener console = new ConsoleTraceListener();
            console.TraceOutputOptions = TraceOptions.Timestamp | TraceOptions.ThreadId;
            SourceSwitch on = new SourceSwitch("app");
            on.Level = SourceLevels.Verbose;
            App.Switch = on;
            App.Listeners.Add(console);
            App.TraceInformation("Trace has been enabled");
        }

        public static void DisableTrace()
        {
            if (App.Switch != null)
            {
                App.Switch.Level = SourceLevels.Off;
            }
            App.TraceInformation("Trace has been enabled");
        }
    }

    public class NativeMethods
    {
        /// <remarks>
        /// 
        ///  USAGE: Place inside your program's main static class
        ///  and call AllocateConsole whenever you want.
        /// </remarks>

        /// <summary>
        /// allocates a new console for the calling process.
        /// </summary>
        /// <returns>If the function succeeds, the return value is nonzero.
        /// If the function fails, the return value is zero. 
        /// To get extended error information, call Marshal.GetLastWin32Error.</returns>
        [DllImport("kernel32", SetLastError = true)]
        private static extern bool AllocConsole();

        /// <summary>
        /// Detaches the calling process from its console
        /// </summary>
        /// <returns>If the function succeeds, the return value is nonzero.
        /// If the function fails, the return value is zero. 
        /// To get extended error information, call Marshal.GetLastWin32Error.</returns>
        [DllImport("kernel32", SetLastError = true)]
        private static extern bool FreeConsole();

        /// <summary>
        /// Attaches the calling process to the console of the specified process.
        /// </summary>
        /// <param name="dwProcessId">[in] Identifier of the process, usually will be ATTACH_PARENT_PROCESS</param>
        /// <returns>If the function succeeds, the return value is nonzero.
        /// If the function fails, the return value is zero. 
        /// To get extended error information, call Marshal.GetLastWin32Error.</returns>
        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern bool AttachConsole(uint dwProcessId);

        /// <summary>Identifies the console of the parent of the current process as the console to be attached.
        /// always pass this with AttachConsole in .NET for stability reasons and mainly because
        /// I have NOT tested interprocess attaching in .NET so dont blame me if it doesnt work! </summary>
        private const uint ATTACH_PARENT_PROCESS = 0x0ffffffff;

        /// <summary>
        /// calling process is already attached to a console
        /// </summary>
        private const int ERROR_ACCESS_DENIED = 5;

        /// <summary>
        /// Allocate a console if application started from within windows GUI. 
        /// Detects the presence of an existing console associated with the application and
        /// attaches itself to it if available.
        /// </summary>
        public static void AllocateConsole()
        {
            //
            // the following should only be used in a non-console application type (C#)
            // (since a console is allocated/attached already when you define a console app.. :) )
            //
            //if (!AttachConsole(ATTACH_PARENT_PROCESS) && Marshal.GetLastWin32Error() == ERROR_ACCESS_DENIED)
            {
                // A console was not allocated, so we need to make one.
                if (!AllocConsole())
                {
                    //MessageBox.Show("A console could not be allocated, sorry!");
                    //throw new Exception("Console Allocation Failed");
                }
                else
                {
                    //Console.WriteLine("Is Attached, press a key...");
                    //Console.ReadKey(true);
                    // you now may use the Console.xxx functions from .NET framework
                    // and they will work as normal
                }

            }
        }
    }
}